package com.kj.tms.common.bean.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: tms
 * @Package: com.hongtu.tms.common.util.redis
 * @Description: redis实现类
 * @Author: [wzl]
 * @CreateDate: 2017/11/17 16:16
 */
@Service
public class RedisAccessImpl implements RedisAccess {
    @Autowired
    private RedisTemplate redisTemplate;

    private static final Logger logger = LoggerFactory
            .getLogger(RedisAccessImpl.class);


    /**
     * @Method      redisTemplateInit
     * @Param
     * @Return      org.springframework.data.redis.core.RedisTemplate
     * @Exception
     * @Description [解决redis存储乱码]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/6/26 15:53
     */
    @Bean
    public RedisTemplate redisTemplateInit() {
        //设置序列化Key的实例化对象
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列化Value的实例化对象
//        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        return redisTemplate;
    }

    public void set(String redisKey, Object object, long seconds,
                    RedisTemplate redisTemplate) {
        if (object != null) {
            if (seconds != -1) {
                redisTemplate.opsForValue().set(redisKey,
                        object,
                        seconds,
                        TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(redisKey, object);
            }
        }
    }

    /**
     * @see RedisAccess#get(String)
     */
    @Override
    public <T> T get(String redisKey) {
        return get(redisKey, redisTemplate);
    }

    public <T> T get(String redisKey, RedisTemplate redisTemplate) {
        Object object = redisTemplate.opsForValue().get(redisKey);
        return (T) object;
    }

    /**
     * @see RedisAccess#setNoExpire(String, Object)
     */
    @Override
    public void setNoExpire(String redisKey, Object object) {
        if (object != null) {
            redisTemplate.opsForValue().set(redisKey, object);
        }
    }

    /**
     * @see RedisAccess#expire(String, long)
     */
    @Override
    public void expire(String redisKey, long seconds) {
        BoundValueOperations opt = redisTemplate.boundValueOps(redisKey);
        opt.expire(seconds, TimeUnit.SECONDS);
    }

    /**
     * @see RedisAccess#hset(String, String, Object, long)
     */
    @Override
    public void hset(String redisKey, String filedKey, Object object,
                     long seconds) {
        if (object != null) {
            BoundHashOperations boundHashOperations = redisTemplate
                    .boundHashOps(redisKey);
            boundHashOperations.put(filedKey, object);
            if (seconds != -1) {
                boundHashOperations.expire(seconds, TimeUnit.SECONDS);
            }
        }
    }

    /**
     * @see RedisAccess#hget(String, String)
     */
    @Override
    public <T> T hget(String redisKey, String hashKey) {
        Object object = redisTemplate.opsForHash().get(redisKey, hashKey);
        return (T) object;
    }


    public String  hgetValue(String redisKey, String hashKey) {
        Object object = redisTemplate.opsForHash().get(redisKey, hashKey);
        return object.toString();
    }


    /**
     * @see RedisAccess#hsetAll(String, Map, long)
     */
    @Override
    public void hsetAll(String redisKey, Map<String, Object> map, long seconds) {
        BoundHashOperations boundHashOperations = redisTemplate
                .boundHashOps(redisKey);
        boundHashOperations.putAll(map);
        if (seconds != -1) {
            boundHashOperations.expire(seconds, TimeUnit.SECONDS);
        }
    }

    /**
     * @see RedisAccess#hgetAll(String)
     */
    @Override
    public Object hgetAll(String redisKey) {
        BoundHashOperations boundHashOperations = redisTemplate
                .boundHashOps(redisKey);
        return boundHashOperations.entries();
    }

    /**
     * @see RedisAccess#delete(String)
     */
    @Override
    public void delete(String redisKey) {
        redisTemplate.delete(redisKey);
    }

    /**
     * @see RedisAccess#hdelete(String, String)
     */
    @Override
    public void hdelete(String redisKey, String hashKey) {
        try {
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        } catch (Exception e) {
            logger.error("hdelete key:" + redisKey + " fieldkey:" + hashKey
                    + " error:", e);
        }
    }

    @Override
    public void hdeleteAll(String redisKey) {

    }

    /**
     * @see RedisAccess#lpush(String, long, Object...)
     */
    @Override
    public Long lpush(String redisKey, long seconds, Object... obj) {
        try {
            BoundListOperations<String, Object> opt = redisTemplate
                    .boundListOps(redisKey);
            Long result = opt.leftPushAll(obj);
            if (seconds != -1) {
                opt.expire(seconds, TimeUnit.SECONDS);
            }
            return result;
        } catch (Exception e) {
            logger.error("leftPushAll key:" + redisKey + " error:", e);
        }
        return null;
    }

    /**
     * @see RedisAccess#lrandge(String, long, long)
     */
    @Override
    public <T> List<T> lrandge(String key, long start, long end) {
        try {
            ListOperations opt = redisTemplate.opsForList();
            return opt.range(key, start, end);
        } catch (Exception e) {
            logger.error("lrandge KEY" + key + "error:", e);
        }
        return null;
    }

    public void lset(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
        } catch (Exception e) {
            logger.error("lset KEY" + key + "error:", e);
        }
    }

    /**
     * @see RedisAccess#lremove(String, long, Object)
     */
    @Override
    public void lremove(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().remove(key, index, value);
        } catch (Exception e) {
            logger.error("lremove KEY" + key + "error:", e);
        }
    }

    /**
     * @see RedisAccess#set(String, Object, long)
     */
    @Override
    public void set(String redisKey, Object object, long seconds) {
        set(redisKey, object, seconds, redisTemplate);
    }

    /**
     * @see RedisAccess#set(String, Object)
     */
    @Override
    public void set(String redisKey, Object object) {
        this.setNoExpire(redisKey, object);
    }


}
